/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 *    David Corbin - Original implementation in PendingChangelistView.
 ******************************************************************************/
package net.sourceforge.perforce.ui.action;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;

import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.api.IWhereResult;
import net.sourceforge.perforce.core.internal.P4TeamProvider;
import net.sourceforge.perforce.core.resources.IP4File;
import net.sourceforge.perforce.ui.PerforceUIPlugin;
import net.sourceforge.perforce.ui.internal.Policy;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.TeamException;

/**
  * @version $Revision: 180 $
  * @author  <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  * @author  <a href="mailto:dcorbin@users.sourceforge.net">David Corbin</a>
  */
public class RevertFromChangelistAction extends PerforceAction 
{
	// ------------------------------------------------------------------------------ Public Methods
	
	/** @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) */
	public void run(IAction action) 
	{
		if (!shouldContinue())
		{
			return;
		}
		
		run(new IRunnableWithProgress() 
		{
			public void run(IProgressMonitor monitor)
				throws InvocationTargetException, InterruptedException 
			{
				IP4File[] files = getSelectedPerforceFiles();
				
				MultiStatus status =
					new MultiStatus(
						PerforceUIPlugin.ID,
						IStatus.ERROR,
						Policy.bind("RevertFromChangelistAction.errorStatusMessage"),  //$NON-NLS-1$
						null);
				
				ArrayList filenameList = new ArrayList();
				monitor.beginTask("", files.length * 200);
				monitor.setTaskName(
					Policy.bind("RevertFromChangelistAction.revertingTask"));          //$NON-NLS-1$
				for (int i = 0; i < files.length && !monitor.isCanceled(); i++)
				{
					try
					{
						IP4File file = files[i];						
						IPerforceServer server = file.getServer();
						
						IWhereResult whereResult = server.where(file.getDepotFilename());
						filenameList.add(whereResult.getLocalFilename());
						monitor.subTask(
							Policy.bind(
								"RevertFromChangelistAction.revertingSubTask",         //$NON-NLS-1$
								whereResult.getLocalFilename())); 
						
						IProgressMonitor subMonitor = Policy.subMonitorFor(monitor, 100);
						server.revert(new String[]{ file.getDepotFilename() }, subMonitor);
					}
					catch (PerforceException e)
					{
						status.merge(e.getStatus());
					}
				}
				
				IWorkspaceRoot root = PerforceUIPlugin.getWorkspace().getRoot();				
				for (Iterator it = filenameList.iterator(); it.hasNext();)
				{
					String filename = (String) it.next();
					
					IFile file = root.getFileForLocation(new Path(filename));
					if (file != null)
					{
						try
						{
							P4TeamProvider provider = P4TeamProvider.getProvider(file);
							
							IProgressMonitor subMonitor = Policy.subMonitorFor(monitor, 100);																					
							provider.refreshState(
								new IResource[]{ file }, IResource.DEPTH_ONE, subMonitor);
						}
						catch (TeamException e)
						{
							status.merge(e.getStatus());
						}
					}					
				}
								
				monitor.done();

				if (!status.isOK())
				{
					displayErrorDialog(status);				
				}
			}
		}, PROGRESS_DIALOG);
	}

	// --------------------------------------------------------------------------- Protected Methods

	/** @see net.sourceforge.perforce.ui.action.PerforceAction#isEnabled() */
	protected boolean isEnabled() throws PerforceException 
	{		
		return true;
	}
	
	// ----------------------------------------------------------------------------- Private Methods
	
	/** Called to ask the user for confirmation.
	  *
	  * @return true if we should continue, false otherwise.
	  */ 
	private boolean shouldContinue() 
	{
		boolean shouldContinue = 
			MessageDialog.openConfirm(
				getShell(),
				Policy.bind("RevertAction.confirmDialogTitle"),                        //$NON-NLS-1$
				Policy.bind("RevertAction.confirmDialogMessage"));                     //$NON-NLS-1$
		return shouldContinue;
	}

	/** Called to display an error dialog for the given status.
	  *
	  * @param status the status 
	  */
	private void displayErrorDialog(final IStatus status) 
	{
		Display display = getShell().getDisplay();
		display.asyncExec(new Runnable()
		{
			public void run() 
			{
				ErrorDialog.openError(
					getShell(),
					Policy.bind("simpleInternal"),                                     //$NON-NLS-1$
					Policy.bind("RevertFromChangelistAction.errorMessage"),            //$NON-NLS-1$
					status);
			}
		});	
	}	
	
	/** Called to retrieve an array of selected changelists. 
	  * 
	  * @return array of selected changelists.
	  */
	private IP4File[] getSelectedPerforceFiles()
	{
		ArrayList resources = null;
		if (!getSelection().isEmpty()) 
		{
			resources = new ArrayList();
			for (Iterator elements = getSelection().iterator(); elements.hasNext();)
			{
				Object next = elements.next();
				if (next instanceof IP4File) 
				{
					resources.add(next);
					continue;
				}
				else
				if (next instanceof IAdaptable) 
				{
					IAdaptable a = (IAdaptable) next;
					Object adapter = a.getAdapter(IP4File.class);
					if (adapter instanceof IP4File) 
					{
						resources.add(adapter);
						continue;
					}
				}
			}
		}
		
		if (resources != null && !resources.isEmpty()) 
		{
			return (IP4File[]) resources.toArray(new IP4File[resources.size()]);
		}
		
		return new IP4File[0];
	}
}
